﻿using Castle.Core.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MySqlX.XDevAPI.Common;
using NetTaste;
using Newtonsoft.Json;
using Ongoal.Quotation.Cap;
using Ongoal.Quotation.Common;
using Ongoal.Quotation.Model;
using Ongoal.Quotation.Redis;
using Ongoal.Quotation.Service;
using Ongoal.Quotation.Sqlsugar;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;

namespace Ongoal.Quotation
{
    /// <summary>
    /// 
    /// </summary>
    public static class ContextBase
    {
        /// <summary>
        /// 往数据库保存一条数据
        /// </summary>
        /// <typeparam name="T">类型(需要是ModelBase的子类)</typeparam>
        /// <param name="obj">实体</param>
        /// <param name="info">实体</param>
        /// <returns>实体信息</returns>
        public static T? Insert<T>(this ICommonBase obj, T info) where T : ModelBase, new()
        {
            info.ID = 0;
            info.ModifyTime = info.CreateTime = DateTime.Now;
            info.ModifyID = info.CreatorID = obj.CurrentUser!.UserID;
            if (info is TreeBase<T>)
            {
                var client = obj.Db!.GetDbContext(string.Empty);
                TreeBase<T> treeNode = GetInsertTreeBase(client, info);

                //TreeBase<T>? treeNode = info as TreeBase<T>;
                //if (treeNode == null)
                //{
                //    throw new Exception("无法识别数据");
                //}
                //treeNode.ID = 0;
                //treeNode.ModifyTime = treeNode.CreateTime = DateTime.Now;
                //treeNode.ModifyID = treeNode.CreatorID = obj.CurrentUser!.UserID;
                //if (treeNode.ParentID.HasValue && treeNode.ParentID.Value > 0)
                //{
                //    //存在父节点，需要查询出父节点并获得相应的值
                //    var parentNode = client.Queryable<T>().Where("Deleted=0 AND ID=@ID", new { ID = treeNode.ParentID.Value }).First() as TreeBase<T>;
                //    if (parentNode != null)
                //    {
                //        treeNode.PropPath = $"{parentNode.PropPath}{parentNode.ID}/";
                //        treeNode.NodeLevel = parentNode.NodeLevel + 1;
                //    }
                //}
                //else
                //{
                //    treeNode.ParentID = 0;
                //    treeNode.PropPath = "/";
                //    treeNode.NodeLevel = 1;
                //}
                treeNode.ID = client.Insertable<T>(treeNode).ExecuteReturnIdentity();
                return treeNode as T;
            }
            else
            {
                info.ID = obj.Db!.GetDbContext(string.Empty).Insertable<T>(info).ExecuteReturnIdentity();
                return info as T;
            }
        }

        /// <summary>
        /// 往数据库保存一条数据并且发布数据
        /// </summary>
        /// <typeparam name="T">类型(需要是ModelBase的子类)</typeparam>
        /// <param name="obj">实体</param>
        /// <param name="info">实体</param>
        /// <param name="publisher">消息发布器</param>
        /// <param name="messageSubscribe">消息主题</param>
        /// <param name="before">before</param>
        /// <param name="end">end</param>
        /// <returns>实体信息</returns>
        public static T? InsertAndPublish<T>(this ICommonBase obj, T info, IMessagePublisher publisher, string messageSubscribe,
            Func<SqlSugarClient, bool>? before = null, Func<SqlSugarClient, bool>? end = null) where T : ModelBase, new()
        {
            var client = obj.Db!.GetDbContext(string.Empty);
            info.ID = 0;
            info.ModifyTime = info.CreateTime = DateTime.Now;
            info.ModifyID = info.CreatorID = obj.CurrentUser!.UserID;

            if (info is TreeBase<T>)
            {
                TreeBase<T> treeNode = GetInsertTreeBase(client, info);

                publisher.ExecuteDBAndPublish(client.Ado, () =>
                {
                    if (before != null)
                    {
                        if (!before(client))
                        {
                            return false;
                        }
                    }
                    treeNode.ID = client.Insertable<T>(treeNode).ExecuteReturnIdentity();
                    if (treeNode.ID <= 0)
                        return false;
                    if (end != null)
                    {
                        if (!end(client))
                        {
                            return false;
                        }
                    }
                    publisher.PublishWithDefaultCallback(messageSubscribe, treeNode);
                    return true;
                });
                return treeNode as T;
            }
            else
            {
                publisher.ExecuteDBAndPublish(client.Ado, () =>
                {
                    info.ID = client.Insertable<T>(info).ExecuteReturnIdentity();
                    if (info.ID <= 0)
                        return false;
                    publisher.PublishWithDefaultCallback(messageSubscribe, info);
                    return true;
                });
                return info;
            }
        }

        private static TreeBase<T> GetInsertTreeBase<T>(SqlSugarClient client, T info) where T : ModelBase
        {
            TreeBase<T>? treeNode = info as TreeBase<T>;
            if (treeNode == null)
            {
                throw new Exception("无法识别数据");
            }

            if (treeNode.ParentID.HasValue && treeNode.ParentID.Value > 0)
            {
                //存在父节点，需要查询出父节点并获得相应的值
                var parentNode = client.Queryable<T>().Where("Deleted=0 AND ID=@ID", new { ID = treeNode.ParentID.Value }).First() as TreeBase<T>;
                if (parentNode != null)
                {
                    treeNode.PropPath = $"{parentNode.PropPath}{parentNode.ID}/";
                    treeNode.NodeLevel = parentNode.NodeLevel + 1;
                }
            }
            else
            {
                treeNode.ParentID = 0;
                treeNode.PropPath = "/";
                treeNode.NodeLevel = 1;
            }

            return treeNode;
        }

        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <typeparam name="T">类型(需要是ModelBase的子类)</typeparam>
        /// <param name="obj"></param>
        /// <param name="info">实体</param>
        /// <returns>实体信息</returns>
        /// <exception cref="Exception"></exception>
        /// <exception cref="ArgumentException"></exception>
        public static T? Update<T>(this ICommonBase obj, T info) where T : ModelBase, new()
        {
            info.ModifyTime = DateTime.Now;
            info.ModifyID = obj.CurrentUser!.UserID;

            using var client = obj.Db!.GetDbContext(string.Empty);
            if (info is TreeBase<T>)
            {
                TreeBase<T>? treeNode = GetUpdateTreeBase(client, info);
                //TreeBase<T>? treeNode = info as TreeBase<T>;
                //if (treeNode == null)
                //{
                //    throw new Exception("无法识别数据");
                //}
                //if (!treeNode.Deleted.HasValue || treeNode.Deleted.Value < 0)
                //{
                //    treeNode.Deleted = 0;
                //}
                //var oldInfo = client.Queryable<T>().Where(t => t.ID == info.ID).First() as TreeBase<T>;
                //if (oldInfo == null)
                //{
                //    throw new ArgumentException("无法找到对应的记录");
                //}
                //if (!treeNode.ParentID.HasValue || oldInfo.ParentID == treeNode.ParentID)
                //{
                //    //没有改变父节点信息，无需修改
                //    treeNode.ParentID = oldInfo.ParentID;
                //    treeNode.PropPath = oldInfo.PropPath;
                //    treeNode.NodeLevel = oldInfo.NodeLevel;
                //}
                //else if (treeNode.ParentID <= 0)
                //{
                //    treeNode.ParentID = 0;
                //    treeNode.PropPath = "/";
                //    treeNode.NodeLevel = 1;
                //}
                //else
                //{
                //    var newParent = client.Queryable<T>().Where("Deleted=0 AND ID=@ID", new { ID = treeNode.ParentID.Value }).First() as TreeBase<T>;
                //    if (newParent == null)
                //    {
                //        throw new ArgumentException("指定了无效的父节点信息");
                //    }
                //    treeNode.PropPath = $"{newParent.PropPath}{newParent.ID}/";
                //    treeNode.NodeLevel = newParent.NodeLevel + 1;
                //}
                client.BeginTran();
                if (client.Updateable<T>(treeNode).ExecuteCommand() == 1)
                {
                    client.CommitTran();
                    return info;
                }
                else
                {
                    client.RollbackTran();
                    throw new ArgumentException("无法找到对应的记录");
                }
            }
            else
            {
                client.BeginTran();
                if (client.Updateable<T>(info).ExecuteCommand() == 1)
                {
                    client.CommitTran();
                    return info;
                }
                else
                {
                    client.RollbackTran();
                    throw new ArgumentException("无法找到对应的记录");
                }
            }
        }

        /// <summary>
        /// 更新一条数据并且发布数据
        /// </summary>
        /// <typeparam name="T">类型(需要是ModelBase的子类)</typeparam>
        /// <param name="obj"></param>
        /// <param name="info">实体</param>
        /// <param name="publisher">消息发布器</param>
        /// <param name="messageSubscribe">消息主题</param>
        /// <param name="before">before</param>
        /// <param name="end">end</param>
        /// <returns>实体信息</returns>
        /// <exception cref="Exception"></exception>
        /// <exception cref="ArgumentException"></exception>
        public static T? UpdateAndPublish<T>(this ICommonBase obj, T info, IMessagePublisher publisher, string messageSubscribe,
             Func<SqlSugarClient, bool>? before = null, Func<SqlSugarClient, bool>? end = null) where T : ModelBase, new()
        {
            info.ModifyTime = DateTime.Now;
            info.ModifyID = obj.CurrentUser!.UserID;

            var client = obj.Db!.GetDbContext(string.Empty);
            if (info is TreeBase<T>)
            {
                TreeBase<T>? treeNode = GetUpdateTreeBase(client, info);

                publisher.ExecuteDBAndPublish(client.Ado, () =>
                {
                    if (before != null)
                    {
                        if (!before(client))
                        {
                            return false;
                        }
                    }
                    if (client.Updateable<T>(treeNode).ExecuteCommand() != 1)
                        throw new ArgumentException("无法找到对应的记录");

                    if (end != null)
                    {
                        if (!end(client))
                        {
                            return false;
                        }
                    }
                    publisher.PublishWithDefaultCallback(messageSubscribe, treeNode);
                    return true;
                });
            }
            else
            {
                publisher.ExecuteDBAndPublish(client.Ado, () =>
                {
                    if (before != null)
                    {
                        if (!before(client))
                        {
                            return false;
                        }
                    }
                    if (client.Updateable<T>(info).ExecuteCommand() != 1)
                        throw new ArgumentException("无法找到对应的记录");
                    if (end != null)
                    {
                        if (!end(client))
                        {
                            return false;
                        }
                    }
                    publisher.PublishWithDefaultCallback(messageSubscribe, info);
                    return true;
                });
            }
            return info;
        }

        private static TreeBase<T> GetUpdateTreeBase<T>(SqlSugarClient client, T info) where T : ModelBase
        {
            TreeBase<T>? treeNode = info as TreeBase<T>;
            if (treeNode == null)
            {
                throw new Exception("无法识别数据");
            }
            if (!treeNode.Deleted.HasValue || treeNode.Deleted.Value < 0)
            {
                treeNode.Deleted = 0;
            }
            var oldInfo = client.Queryable<T>().Where(t => t.ID == info.ID).First() as TreeBase<T>;
            if (oldInfo == null)
            {
                throw new ArgumentException("无法找到对应的记录");
            }
            if (!treeNode.ParentID.HasValue || oldInfo.ParentID == treeNode.ParentID)
            {
                //没有改变父节点信息，无需修改
                treeNode.ParentID = oldInfo.ParentID;
                treeNode.PropPath = oldInfo.PropPath;
                treeNode.NodeLevel = oldInfo.NodeLevel;
            }
            else if (treeNode.ParentID <= 0)
            {
                treeNode.ParentID = 0;
                treeNode.PropPath = "/";
                treeNode.NodeLevel = 1;
            }
            else
            {
                var newParent = client.Queryable<T>().Where("Deleted=0 AND ID=@ID", new { ID = treeNode.ParentID.Value }).First() as TreeBase<T>;
                if (newParent == null)
                {
                    throw new ArgumentException("指定了无效的父节点信息");
                }
                treeNode.PropPath = $"{newParent.PropPath}{newParent.ID}/";
                treeNode.NodeLevel = newParent.NodeLevel + 1;
            }
            return treeNode;
        }

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <typeparam name="T">类型(需要是ModelBase的子类)</typeparam>
        /// <param name="obj"></param>
        /// <param name="idList">数据ID数组</param>
        /// <returns>成功与否</returns>
        public static bool Delete<T>(this ICommonBase obj, params int[] idList) where T : ModelBase, new()
        {
            if (idList.Length > 0)
            {
                using var client = obj.Db!.GetDbContext(string.Empty);
                client.BeginTran();
                if (typeof(T).IsSubclassOf(typeof(TreeBase<T>)))
                {
                    var updateObj = new Dictionary<string, object>();
                    updateObj.Add("", 1);
                    //树形表，则是更新其删除状态
                    if (client.Updateable<T>().SetColumns("Deleted", 1).Where(t => idList.Contains(t.ID)).ExecuteCommand() == idList.Length)
                    {
                        client.CommitTran();
                        return true;
                    }
                    else
                    {
                        client.RollbackTran();
                        return false;
                    }
                }
                else
                {
                    if (client.Deleteable<T>(idList).ExecuteCommand() == idList.Length)
                    {
                        client.CommitTran();
                        return true;
                    }
                    else
                    {
                        client.RollbackTran();
                        return false;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <typeparam name="T">类型(需要是ModelBase的子类)</typeparam>
        /// <param name="obj"></param>
        /// <param name="idList">数据ID数组</param>
        /// <param name="publisher"></param>
        /// <param name="messageSubscribe"></param>
        /// <param name="before">before</param>
        /// <param name="end">end</param>
        /// <returns>成功与否</returns>
        public static bool DeleteAndPublish<T>(this ICommonBase obj, int[] idList, IMessagePublisher publisher, string messageSubscribe,
            Func<SqlSugarClient, bool>? before = null, Func<SqlSugarClient, bool>? end = null) where T : ModelBase, new()
        {
            if (idList == null || idList.Count() == 0)
            {
                throw new ArgumentNullException("删除参数异常");
            }

            var client = obj.Db!.GetDbContext(string.Empty);
            bool result = publisher.ExecuteDBAndPublish(client.Ado, () =>
            {
                if (typeof(T).IsSubclassOf(typeof(TreeBase<T>)))
                {
                    var updateObj = new Dictionary<string, object>();
                    updateObj.Add("", 1);
                    if (before != null)
                    {
                        if (!before(client))
                        {
                            return false;
                        }
                    }
                    //树形表，则是更新其删除状态
                    if (client.Updateable<T>().SetColumns("Deleted", 1).Where(t => idList.Contains(t.ID)).ExecuteCommand() != idList.Length)
                    {
                        return false;
                    }
                    if (end != null)
                    {
                        if (!end(client))
                        {
                            return false;
                        }
                    }
                }
                else
                {
                    if (before != null)
                    {
                        if (!before(client))
                        {
                            return false;
                        }
                    }
                    if (client.Deleteable<T>(idList).ExecuteCommand() != idList.Length)
                    {
                        return false;
                    }
                    if (end != null)
                    {
                        if (!end(client))
                        {
                            return false;
                        }
                    }
                }
                publisher!.PublishWithDefaultCallback(messageSubscribe, idList);

                return true;
            });

            return result;
        }
    }
}
